﻿using System;
using System.Collections.Generic;
using System.Linq;
using Entity;
using IBusinessLogicLayer;
using IDataAccessLayer;
using Infrastructure;
using BusinessLogicLayer.Dto;

namespace BusinessLogicLayer
{
    public class ShoppingCartBll : BaseBll<Cart>, IShoppingCartBll
    {
        private const string ShoppingCartCookie = "shoppingcart";
        private IBaseDal<Cart> dal;
        private IBaseDal<Album> albumDal;
        public ShoppingCartBll(IBaseDal<Cart> dal, IBaseDal<Album> albumDal) : base(dal)
        {
            this.dal = dal;
            this.albumDal = albumDal;
        }

        public bool AddCart(Cart cart)
        {
            //todo:相同专辑应该合并
            var userId = cart.UserId;
            if (string.IsNullOrEmpty(userId))
            {
                var carts = GetCartsFromCookie().ToList();
                var index = carts.FindIndex(c => c.AlbumId == cart.AlbumId);
                if (index>=0)
                {
                    carts[0].Count += cart.Count;
                }
                else
                {
                    carts.Add(cart);
                }
                WriteCartsToCookie(carts);
                return true;
            }
            else
            {
                var cartInDb = dal.FindSingle(c => c.AlbumId == cart.AlbumId && c.UserId == cart.UserId);
                if (cartInDb == null)
                {
                    return dal.Insert(cart);
                }
                else
                {

                    return dal.Update(c => c.AlbumId == cart.AlbumId && c.UserId == cart.UserId,
                        c => new Cart() {Count = cartInDb.Count + cart.Count});
                }
            }
        }

        public bool EmptyCart(string userId = null)
        {
            if (string.IsNullOrEmpty(userId))
            {
                EmptyCartFromCookie();
                return true;
            }
            else
            {
                return dal.Delete(c => c.UserId == userId, true);
            }
        }

        public IEnumerable<Cart> GetCarts(string userId = null)
        {

            if (string.IsNullOrEmpty(userId))
            {
                var carts= GetCartsFromCookie().ToList();
                for (int i = 0; i < carts.Count; i++)
                {
                    var temp = carts[i].AlbumId;
                    carts[i].Album = albumDal.FindSingle(a => a.Id ==temp );
                }
                
                return carts;
            }
            else
            {
                return dal.GetQueryable().Where(c => c.UserId == userId);
            }
        }

        public int GetCount(string userId = null)
        {
            var count = 0;
            if (string.IsNullOrEmpty(userId))
            {
                count = GetCartsFromCookie().Count();
            }
            else
            {
                count = dal.GetQueryable().Where(c => c.UserId == userId).Count();
            }
             return count;
        }

        public decimal GetTotal(string userId = null)
        {
            var carts = GetCarts(userId).ToList();
            var cartsAlbumIds = carts.Select(c => c.AlbumId);
            var albums =
                albumDal.GetQueryable()
                    .Where(a => cartsAlbumIds.Contains(a.Id))
                    .Select(a => new { a.Id, a.Price })
                    .ToDictionary(d => d.Id, d => d.Price);
            var total = decimal.Zero;
            foreach (var cart in carts)
            {
                total += cart.Count * albums[cart.AlbumId];
            }
            return total;
        }

        public bool RmoveFromCart(Cart cart)
        {
            var userId = cart.UserId;
            if (string.IsNullOrEmpty(userId))
            {
                var carts = GetCartsFromCookie().ToList();
                carts.RemoveAll(c=>c.AlbumId==cart.AlbumId);
                WriteCartsToCookie(carts);
                return true;
            }
            else
            {
                return dal.Delete(c=>c.AlbumId==cart.AlbumId&&c.UserId==userId);
            }
        }

        private IEnumerable<Cart> GetCartsFromCookie()
        {
            var cookieValue = CookieHelper.GetCookie(ShoppingCartCookie);
            if (string.IsNullOrEmpty(cookieValue)) return new List<Cart>();
            return SerializeHelper.Deserialize<IList<CartDto>>(cookieValue).Select(x => new Cart()
            {
                Id = x.Id,
                AlbumId = x.AlbumId,
                Count = x.Count,
                DateCreated = x.DateCreated,
                UserId = x.UserId
            });
        }

        private void WriteCartsToCookie(IEnumerable<Cart> carts)
        {
            CookieHelper.WriteCookie(ShoppingCartCookie, SerializeHelper.Serialize<IList<CartDto>>(carts.Select(x => new CartDto(){Id = x.Id,AlbumId = x.AlbumId,Count = x.Count,DateCreated = x.DateCreated,UserId = x.UserId}).ToList()));
        }

        private void EmptyCartFromCookie()
        {
            CookieHelper.WriteCookie(ShoppingCartCookie, "");
        }

        public bool SaveCartsFromCookie(string userId)
        {
            //应该批量更新 而不是多次执行
            var carts = GetCartsFromCookie();
            foreach (var cart in carts)
            {
                cart.UserId = userId;
                dal.Insert(cart);
            }
            EmptyCartFromCookie();
            return true;

        }
    }
}